package practica1.ui.simulacion;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import practica1.Practica1;
import practica1.domain.SimulacionBacterias;
import practica1.domain.SimulacionBacteriasEvent;
import practica1.domain.SimulacionBacteriasListener;
import practica1.language.Language;
import practica1.language.LanguageEvent;
import practica1.language.LanguageListener;
import practica1.logic.LogicPoblacion;
import practica1.util.Utils;

/**
 *
 * @author Miguel González - Ceura
 */
public class PanelSimulacionBacterias extends JPanel
        implements SimulacionBacteriasListener, LanguageListener {
    
    private ThreadSimulacion threadSimulacion;
    private SimulacionBacterias simulacionBacterias;
    private LogicPoblacion poblacion;

    private JPanel panelSuperior;
    private PanelPintadoBacterias pintadoBacterias;
    private JButton btnIniciarSimulacion;
    /**
     * Componente que muestra el progreso de la simulación
     */
    private JProgressBar progresoSimulacion;
    /*
     * Componentes swing que muestran la información de la simulación
     */
    private JPanel panelInformacion;
    private JLabel lblNumDiasDesc;
    private JLabel lblNumDias;
    private JLabel lblAlimentoInicialDesc;
    private JLabel lblAlimentoInicial;
    private JLabel lblDiaMaxDesc;
    private JLabel lblDiaMax;
    private JLabel lblAlimentoMaxDesc;
    private JLabel lblAlimentoMax;
    private JLabel lblAlimentoFinalDesc;
    private JLabel lblAlimentoFinal;
    private JLabel lblLadoPlatoDesc;
    private JLabel lblLadoPlato;
    private JLabel lblPoblacionInicialDesc;
    private JLabel lblPoblacionInicial;
    
    /*
     * Componentes para el manejo de la simulación
     */
    private JRadioButton rdbVerBacterias;
    private JRadioButton rdbVerComida;
    private JPanel panelControles;
    private JButton btnAvanzar;
    private JButton btnRetroceder;
    private JLabel lblDiaSimulacionDesc;
    private JLabel lblDiaSimulacion;
    /*
     * Tabla con la información diaria de la comida, bacterias y bacterias muertas
     */
    private JTable tablaInformacion;
    private ModeloSimulacionTabla modeloTablaInformacion;
    
    public PanelSimulacionBacterias(LogicPoblacion poblacion) {
        threadSimulacion = null;
        this.poblacion = poblacion;
        
        simulacionBacterias = poblacion.getSimulacionBacterias();
        
        initComponentes();
        
        initSwing();
        
        initComponentesListeners();
    }

    private void initComponentes() {
        panelSuperior = new JPanel(new BorderLayout());
        /*
         * Barra de progreso
         */
        progresoSimulacion = new JProgressBar(
                JProgressBar.HORIZONTAL, 0, poblacion.getExperimentoPadre().
                getNumDiasExperimento());
        /*
         * Panel información
         */
        panelInformacion = new JPanel(new GridBagLayout());
        lblNumDiasDesc = new JLabel(Language.getI().getP("DURACION_EXPERIMENTO_DIAS"));
        lblNumDias = new JLabel();
        
        lblAlimentoInicialDesc = new JLabel(Language.getI().getP(
                "ALIMENTACION_INICIAL") + ": ");
        lblAlimentoInicial = new JLabel();
        
        lblDiaMaxDesc = new JLabel(Language.getI().getP("DIA_MAXIMO") + ": ");
        lblDiaMax = new JLabel();
        
        lblAlimentoMaxDesc = new JLabel(Language.getI().getP(
                "ALIMENTACION_MAXIMA") + ": ");
        lblAlimentoMax = new JLabel();
        
        lblAlimentoFinalDesc = new JLabel(Language.getI().getP(
                "ALIMENTACION_FINAL") + ": ");
        lblAlimentoFinal = new JLabel();
        
        lblLadoPlatoDesc = new JLabel(Language.getI().getP("LADO_PLATO") + ": ");
        lblLadoPlato = new JLabel();
        
        lblPoblacionInicialDesc = new JLabel(Language.getI().getP(
                "POBLACION_INICIAL") + ": ");
        lblPoblacionInicial = new JLabel();
        
        if(simulacionBacterias.getBacteriasPlato() == null ||
                simulacionBacterias.getComidaPlato() == null) {
            lblNumDias.setText("-");
            lblAlimentoInicial.setText("-");
            lblDiaMax.setText("-");
            lblAlimentoMax.setText("-");
            lblAlimentoFinal.setText("-");
            lblLadoPlato.setText("-");
            lblPoblacionInicial.setText("-");
        } else {
            lblPoblacionInicial.setText(simulacionBacterias.getTamanioPoblacion() + "");
            lblNumDias.setText(simulacionBacterias.getNumDias() + "");
            lblLadoPlato.setText(simulacionBacterias.getLadoPlato() + "");
            lblAlimentoInicial.setText(simulacionBacterias.getAlimentoInicial() + "");
            lblDiaMax.setText(simulacionBacterias.getDiaMax() + "");
            lblAlimentoMax.setText(simulacionBacterias.getAlimentoMax() + "");
            lblAlimentoFinal.setText(simulacionBacterias.getAlimentoFinal() + "");
        }
        
        /*
         * Panel del manejo de la simulación
         */
        panelControles = new JPanel(new FlowLayout(FlowLayout.CENTER));
        btnAvanzar = new JButton(Language.getI().getP("AVANZAR"));
        btnRetroceder = new JButton(Language.getI().getP("RETROCEDER"));
        lblDiaSimulacionDesc = new JLabel(Language.getI().getP(
                "DIA_MOSTRADO") + ": ");
        
        rdbVerBacterias = new JRadioButton(Language.getI().getP("VER_BACTERIAS"));
        rdbVerBacterias.setSelected(true);
        rdbVerComida = new JRadioButton(Language.getI().getP("VER_COMIDA"));
        
        ButtonGroup group = new ButtonGroup();
        group.add(rdbVerBacterias);
        group.add(rdbVerComida);
        
        btnRetroceder.setEnabled(false);
        lblDiaSimulacion = new JLabel();
        if(simulacionBacterias.getBacteriasPlato() == null ||
                simulacionBacterias.getComidaPlato() == null) {
            lblDiaSimulacion.setText("-");
            btnAvanzar.setEnabled(false);
        } else {
            lblDiaSimulacion.setText("1");
        }
        
        /*
         * Panel donde se pinta la simulación de cada día
         */
        pintadoBacterias = new PanelPintadoBacterias();
        if(simulacionBacterias.getBacteriasPlato() != null &&
                simulacionBacterias.getComidaPlato() != null) {
            pintadoBacterias.pintarBacterias(
                    simulacionBacterias.getBacteriasPlatoDia(1),
                    simulacionBacterias.getComidaPlatoDia(1),
                    rdbVerComida.isSelected());
        }
        /*
         * Tabla con la información diaria
         */
        modeloTablaInformacion = new ModeloSimulacionTabla(obtenerDatosTabla(), 
                new String[]{Language.getI().getP("DIA"),
                    Language.getI().getP("COMIDA"),
                    Language.getI().getP("BACTERIAS")});
        
        tablaInformacion = new JTable(modeloTablaInformacion);
        
        
        /*
         * Botón para iniciar la simulación
         */
        btnIniciarSimulacion = new JButton(Language.getI().getP(
                "INICIAR_SIMULACION"));
    }
    
    class EscuchadorRadioButtons implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            if(poblacion.getSimulacionBacterias().getBacteriasPlato() != null &&
                    poblacion.getSimulacionBacterias().getComidaPlato() != null) {
                int dia = Integer.parseInt(lblDiaSimulacion.getText());

                pintadoBacterias.pintarBacterias(
                        simulacionBacterias.getBacteriasPlatoDia(dia),
                        simulacionBacterias.getComidaPlatoDia(dia), 
                        rdbVerComida.isSelected());
            }
        }
    }
    
    private void initSwing() {
        setLayout(new BorderLayout());
        
        GridBagConstraints c = new GridBagConstraints();
        c.fill = GridBagConstraints.HORIZONTAL;
        
        /*
         * Barra de progreso por defecto oculta
         */
        if(poblacion.isSimulando()) {
            btnAvanzar.setEnabled(false);
            btnRetroceder.setEnabled(false);
            btnIniciarSimulacion.setEnabled(false);
        } else {
            progresoSimulacion.setVisible(false);
        }
        /*
         * Colocamos los componentes del panel de información
         */
        panelInformacion.setBorder(BorderFactory.createEmptyBorder(100,10,100,10));
        c.gridx = 0;
        c.gridy = 0;
        panelInformacion.add(lblNumDiasDesc, c);
        c.gridx = 1;
        c.gridy = 0;
        panelInformacion.add(lblNumDias, c);
        c.gridx = 0;
        c.gridy = 1;
        panelInformacion.add(lblAlimentoInicialDesc, c);
        c.gridx = 1;
        c.gridy = 1;
        panelInformacion.add(lblAlimentoInicial, c);
        c.gridx = 0;
        c.gridy = 2;
        panelInformacion.add(lblDiaMaxDesc, c);
        c.gridx = 1;
        c.gridy = 2;
        panelInformacion.add(lblDiaMax, c);
        c.gridx = 0;
        c.gridy = 3;
        panelInformacion.add(lblAlimentoMaxDesc, c);
        c.gridx = 1;
        c.gridy = 3;
        panelInformacion.add(lblAlimentoMax, c);
        c.gridx = 0;
        c.gridy = 4;
        panelInformacion.add(lblAlimentoFinalDesc, c);
        c.gridx = 1;
        c.gridy = 4;
        panelInformacion.add(lblAlimentoFinal, c);
        c.gridx = 0;
        c.gridy = 5;
        panelInformacion.add(lblLadoPlatoDesc, c);
        c.gridx = 1;
        c.gridy = 5;
        panelInformacion.add(lblLadoPlato, c);
        c.gridx = 0;
        c.gridy = 6;
        panelInformacion.add(lblPoblacionInicialDesc, c);
        c.gridx = 1;
        c.gridy = 6;
        panelInformacion.add(lblPoblacionInicial, c);
        c.gridx = 0;
        c.gridy = 7;
        c.gridwidth = 2;
        panelInformacion.add(rdbVerBacterias, c);
        c.gridx = 0;
        c.gridy = 8;
        c.gridwidth = 2;
        panelInformacion.add(rdbVerComida, c);
        
        /*
         * Colocamos los componentes del manejo de la simulación
         * 
         */
        panelControles.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
        panelControles.add(btnRetroceder);
        panelControles.add(lblDiaSimulacionDesc);
        panelControles.add(lblDiaSimulacion);
        panelControles.add(btnAvanzar);
        
        /*
         * Colocación de los paneles
         */
        panelSuperior.add(progresoSimulacion, BorderLayout.NORTH);
        panelSuperior.add(panelInformacion, BorderLayout.WEST);
        panelSuperior.add(panelControles, BorderLayout.SOUTH);
        panelSuperior.add(pintadoBacterias, BorderLayout.CENTER);
        add(panelSuperior, BorderLayout.NORTH);
        add(new JScrollPane(tablaInformacion), BorderLayout.CENTER);
        add(btnIniciarSimulacion, BorderLayout.SOUTH);
    }
    
    private String[][] obtenerDatosTabla() {
        String[][] datos = new String[poblacion.getNumDias()][3];
        
        if(simulacionBacterias.getBacteriasPlato() != null &&
                simulacionBacterias.getComidaPlato() != null) {

            for(int i=0; i<poblacion.getExperimentoPadre().
                        getNumDiasExperimento(); i++) {
                int bacteriasDia[][] = simulacionBacterias.getBacteriasPlatoDia(i+1);
                int comidaDia[][] = simulacionBacterias.getComidaPlatoDia(i+1);

                int comidaTotal = 0;
                for(int j=0; j<comidaDia.length; j++) {
                    for(int k=0; k<comidaDia[j].length; k++) {
                        comidaTotal+= comidaDia[j][k];
                    }
                }

                int bacteriasTotal = 0;
                for(int j=0; j<bacteriasDia.length; j++) {
                    for(int k=0; k<bacteriasDia[j].length; k++) {
                        bacteriasTotal+= bacteriasDia[j][k];
                    }
                }

                //"Día", "Comida", "Bacterias"
                datos[i][0] = "" + (i+1);
                datos[i][1] = "" + comidaTotal;
                datos[i][2] = "" + bacteriasTotal;
            }
        } else {
            datos = new String[0][3];
        }
        
        return datos;
    }
    
    private void initComponentesListeners() {
        Language.getI().addLanguageListener(this);
        
        simulacionBacterias.addSimulacionBacteriasListener(this);
        
        btnIniciarSimulacion.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String ladoPlato = JOptionPane.showInputDialog(
                    Practica1.getInstance(),
                    Language.getI().getP("LADO_PLATO"),
                    Language.getI().getP(
                    "SIMULACION"),
                    JOptionPane.QUESTION_MESSAGE);
                
                if(Utils.esNumero(ladoPlato)) {
                    btnIniciarSimulacion.setEnabled(false);
                    btnRetroceder.setEnabled(false);
                    btnAvanzar.setEnabled(false);

                    threadSimulacion = new ThreadSimulacion(poblacion,
                            Integer.parseInt(ladoPlato));
                    threadSimulacion.addCalculosSimulacionListener(simulacionBacterias);
                    threadSimulacion.start();
                } else {
                    JOptionPane.showMessageDialog(
                        Practica1.getInstance(),
                        Language.getI().getP("INTRODUCE_NUMERO_VALIDO"));
                }
            }
        });
        
        btnAvanzar.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int diaMover = Integer.parseInt(lblDiaSimulacion.getText()) + 1;
                lblDiaSimulacion.setText("" + diaMover);
                if(diaMover == poblacion.getExperimentoPadre().getNumDiasExperimento()) {
                    btnAvanzar.setEnabled(false);
                }
                btnRetroceder.setEnabled(true);
                
                pintadoBacterias.pintarBacterias(
                simulacionBacterias.getBacteriasPlatoDia(diaMover),
                simulacionBacterias.getComidaPlatoDia(diaMover),
                rdbVerComida.isSelected());
            }
        });
        
        btnRetroceder.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int diaMover = Integer.parseInt(lblDiaSimulacion.getText()) - 1;
                lblDiaSimulacion.setText("" + diaMover);
                if(diaMover == 1) {
                    btnRetroceder.setEnabled(false);
                }
                if(poblacion.getExperimentoPadre().getNumDiasExperimento() > 1) {
                    btnAvanzar.setEnabled(true);
                }
                pintadoBacterias.pintarBacterias(
                    simulacionBacterias.getBacteriasPlatoDia(diaMover),
                    simulacionBacterias.getComidaPlatoDia(diaMover), 
                    rdbVerComida.isSelected());
            } 
        });
        
        rdbVerBacterias.addActionListener(new EscuchadorRadioButtons());
        rdbVerComida.addActionListener(new EscuchadorRadioButtons());
    }

    @Override
    public void simulacionBacteriasChange(SimulacionBacteriasEvent evt) {
        btnIniciarSimulacion.setEnabled(true);
        lblDiaSimulacion.setText("1");
        btnAvanzar.setEnabled(true);

        modeloTablaInformacion.setDataVector(obtenerDatosTabla());
        tablaInformacion.repaint();

        pintadoBacterias.pintarBacterias(
                simulacionBacterias.getBacteriasPlatoDia(1),
                simulacionBacterias.getComidaPlatoDia(1),
                rdbVerComida.isSelected());

        lblNumDias.setText(simulacionBacterias.getNumDias() + "");
        lblAlimentoInicial.setText(simulacionBacterias.getAlimentoInicial() + "");
        lblDiaMax.setText(simulacionBacterias.getDiaMax() + "");
        lblAlimentoMax.setText(simulacionBacterias.getAlimentoMax() + "");
        lblAlimentoFinal.setText(simulacionBacterias.getAlimentoFinal() + "");
        lblLadoPlato.setText(simulacionBacterias.getLadoPlato() + "");
        lblPoblacionInicial.setText(simulacionBacterias.getTamanioPoblacion() + "");
    }

    @Override
    public void terminadaSimulacion() {
        progresoSimulacion.setVisible(false);
    }

    @Override
    public void simulacionAcabadaDia(int numDia, int [][]comidaDia,
            int [][]bacteriasDia) {
        
        lblNumDias.setText("Simulando...");
        lblAlimentoInicial.setText("Simulando...");
        lblDiaMax.setText("Simulando...");
        lblAlimentoMax.setText("Simulando...");
        lblAlimentoFinal.setText("Simulando...");
        lblLadoPlato.setText("Simulando...");
        lblPoblacionInicial.setText("Simulando...");
        
        lblDiaSimulacion.setText("" + numDia);
        btnAvanzar.setEnabled(false);
        btnRetroceder.setEnabled(false);
        btnIniciarSimulacion.setEnabled(false);
        progresoSimulacion.setValue(numDia);
        
        pintadoBacterias.pintarBacterias(
                bacteriasDia, comidaDia, rdbVerComida.isSelected());
    }

    @Override
    public void empezadaSimulacion() {
        progresoSimulacion.setVisible(true);
        progresoSimulacion.setValue(0);
    }

    @Override
    public void idiomaChange(LanguageEvent evt) {
        lblNumDiasDesc.setText(Language.getI().getP("DURACION_EXPERIMENTO_DIAS"));
        lblAlimentoInicialDesc.setText(Language.getI().getP(
                "ALIMENTACION_INICIAL") + ": ");
        lblDiaMaxDesc.setText(Language.getI().getP("DIA_MAXIMO") + ": ");
        lblAlimentoMaxDesc.setText(Language.getI().getP(
                "ALIMENTACION_MAXIMA") + ": ");
        lblAlimentoFinalDesc.setText(Language.getI().getP(
                "ALIMENTACION_FINAL") + ": ");
        lblLadoPlatoDesc.setText(Language.getI().getP("LADO_PLATO") + ": ");
        lblPoblacionInicialDesc.setText(Language.getI().getP(
                "POBLACION_INICIAL") + ": ");
        btnAvanzar.setText(Language.getI().getP("AVANZAR"));
        btnRetroceder.setText(Language.getI().getP("RETROCEDER"));
        lblDiaSimulacionDesc.setText(Language.getI().getP(
                "DIA_MOSTRADO") + ": ");
        btnIniciarSimulacion.setText(Language.getI().getP(
                "INICIAR_SIMULACION"));
        
        rdbVerBacterias.setText(Language.getI().getP("VER_BACTERIAS"));
        rdbVerComida.setText(Language.getI().getP("VER_COMIDA"));
        
        tablaInformacion.getColumnModel().getColumn(0).setHeaderValue(
                Language.getI().getP("DIA"));
        tablaInformacion.getColumnModel().getColumn(1).setHeaderValue(
                Language.getI().getP("COMIDA"));
        tablaInformacion.getColumnModel().getColumn(2).setHeaderValue(
                Language.getI().getP("BACTERIAS"));
    }
}
